/*
**    Copyright (C) 2003-2011 Institute for Systems Biology
**                            Seattle, Washington, USA.
**
**    This library is free software; you can redistribute it and/or
**    modify it under the terms of the GNU Lesser General Public
**    License as published by the Free Software Foundation; either
**    version 3 of the License, or (at your option) any later version.
**
**    This library is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
**    Lesser General Public License for more details.
**
**    You should have received a copy of the GNU Lesser General Public
**    License along with this library; if not, write to the Free Software
**    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*/

package org.systemsbiology.util;

public class Pair<P, Q>{
	public P first;
	public Q second;

	public Pair(P first, Q second){
		this.first = first;
		this.second = second;
	}
	public Pair(){
		this.first = null;
		this.second = null;
	}

    public Pair(Pair<? extends P, ? extends Q> copyMe){
        this.first = copyMe.first;
        this.second = copyMe.second;
    }

	public int hashCode(){
		int h = second.hashCode();
		h = h << 16 ^ h >>> 16;
		return h ^ first.hashCode();
	}
	
	public boolean equals(Object o){
		if(o == null) return false;
		if(o.getClass() != this.getClass()){ //too bad classes don't include derived type!
			return false;
		}
		
		//there is no way in hell I can avoid the next cast
		@SuppressWarnings("unchecked")
		Pair<? extends Object, ? extends Object> p = (Pair<? extends Object, ? extends Object>) o;
		
		if(first == null && p.first == null && second == null && p.second == null){return true;}
		if(first == null){
			if(p.first != null){return false;}
			return second.equals(p.second);
		}
		if(second == null){
			if(p.second != null){return false;}
			return first.equals(p.first);
		}
		
		return first.equals(p.first) && second.equals(p.second);
	}
	
	public String toString(){
		return "Pair:{" + first + ", " + second +"}";
	}
	
	public Pair<Q, P> makeReverse(){
		return new Pair<Q, P>(second, first);
	}

    /**
     * Utility method equivalent to C++'s STL pair::make_pair method. Just a typing shortcut to avoid writing out
     * your data types several times. May result in unexpected data types.
     * @param p First value for the pair.
     * @param q Second value for the pair.
     * @param <P> Type of the first value.
     * @param <Q> Type of the second value.
     * @return The pair of the specified values.
     */
    public static <P, Q> Pair<P, Q> makePair(P p, Q q){
        return new Pair<P, Q>(p, q);
    }
}
